﻿using DryIoc;
using PLCSharp.CoreModel.Common;
using PLCSharp.CoreModel.Prism;
using PLCSharp.CoreModel.Tools;
using PLCSharp.Models;
using Prism.Commands;
using Prism.Dialogs;
using Prism.Ioc;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;

namespace PLCSharp.Views.Connects.Socket
{

    public class SocketServerConfigViewModel : ValidateBase, IDialogAware
    {
        public SocketServerConfigViewModel(IContainerExtension container)
        {
            _ConnectsModel = container.Resolve<ConnectsModel>();
            bkgWorker = new BackgroundWorker { WorkerSupportsCancellation = true };
            bkgWorker.DoWork += BackgroundWork;

            if (!bkgWorker.IsBusy)
                bkgWorker.RunWorkerAsync();
        }

        private readonly ConnectsModel _ConnectsModel;
        private string _Title = "Socket Server";

        public string Title
        {
            get { return _Title; }
            set
            {
                SetProperty(ref _Title, value);
            }
        }

        public DialogCloseListener RequestClose { get; }

        public bool CanCloseDialog()
        {
            return true;
        }

        public void OnDialogClosed()
        {
            Server.LogSwitch = false;
            bkgWorker.CancelAsync();
            bkgWorker.Dispose();
        }

        public void OnDialogOpened(IDialogParameters parameters)
        {
            var name = parameters.GetValue<string>("Name");

            Server = _ConnectsModel.Connects.Where(c => c.Name == name).FirstOrDefault();

            IP = Server.IP;
            Port = Server.Port;
            Server.LogSwitch = true;


        }

        private readonly BackgroundWorker bkgWorker;

        private void BackgroundWork(object sender, DoWorkEventArgs e)
        {
            var worker = (BackgroundWorker)sender;

            while (!worker.CancellationPending)
            {
                Thread.Sleep(10);
                if (Server != null)
                {

                    for (int i = 0; i < Server.Clients.Count; i++)
                    {
                        Server.Clients[i].Online = NetTool.PingIP(Server.Clients[i].IP);

                    }
                    if (Server.LogSwitch)
                    {
                        if (!(Server as SocketServer).LogQueue.IsEmpty)
                        {
                            if ((Server as SocketServer).LogQueue.TryDequeue(out string log))

                                System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                                {
                                    Logs.Add(new(log));
                                }));
                        }
                    }
                }

            }
        }


        private Connect _Server;
        /// <summary>
        /// Comment
        /// </summary>
        public Connect Server
        {
            get { return _Server; }
            set { SetProperty(ref _Server, value); }
        }

        private Connect _SelectedClient;
        /// <summary>
        /// Comment
        /// </summary>
        public Connect SelectedClient
        {
            get { return _SelectedClient; }
            set
            {
                SetProperty(ref _SelectedClient, value);
                if (value != null)
                {
                    Server.Params.DataType = value.Params.DataType;

                }

            }
        }
        //日志
        private ObservableCollection<ErrorLog> _Logs = [];

        public ObservableCollection<ErrorLog> Logs
        {
            get { return _Logs; }
            set { SetProperty(ref _Logs, value); }
        }

        // IP
        private string _IP = "127.0.0.1";

        [Required(ErrorMessage = "IP不能为空！")]
        [RegularExpression(@"^([1-9]\d?|1\d{2}|2[01]\d|22[0-3])(\.([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])){3}$", ErrorMessage = "IP地址格式不正确")]
        public string IP
        {
            get { return _IP; }
            set
            {
                SetProperty(ref _IP, value);
                Server.IP = value;
            }
        }

        // PORT
        private int _Port = 7950;

        [Required(ErrorMessage = "端口不能为空！")]
        [Range(0, 65535, ErrorMessage = "端口应在0-65535之间.")]
        public int Port
        {
            get { return _Port; }
            set
            {
                SetProperty(ref _Port, value);

                Server.Port = value;
            }
        }


        private string _SendString = "hello";

        public string SendString
        {
            get { return _SendString; }
            set
            {
                SetProperty(ref _SendString, value);
            }
        }

        #region Command

        private AsyncDelegateCommand _Send;

        public AsyncDelegateCommand Send =>
            _Send ??= new AsyncDelegateCommand(ExecuteSendAsync);


        private async Task ExecuteSendAsync()

        {
            if (SelectedClient == null)
            {

                Server.Log("请选择客户端"); return;

            }

            await Server.SendAsync(SendString, SelectedClient.Name);
            if (Server.Params.DataType == CommunicationDataType.Bytes) {

                SendString = Server.SendInfo;
            
            }

        }
        private AsyncDelegateCommand _SendToAll;
        public AsyncDelegateCommand SendToAll =>
            _SendToAll ??= new AsyncDelegateCommand(ExecuteSendToAllAsync);

        private async Task ExecuteSendToAllAsync()
        {
            await Server.SendAsync(SendString);
            if (Server.Params.DataType == CommunicationDataType.Bytes)
            {
                SendString = Server.SendInfo;
            }
        }
        private DelegateCommand<string> _ConnectsManage;

        public DelegateCommand<string> ConnectsManage =>
            _ConnectsManage ??= new DelegateCommand<string>(ExecuteConnectsManage);

        private void ExecuteConnectsManage(string cmd)
        {
            switch (cmd)
            {
                case "New":
                    Server.Clients.Add(new Connect()
                    {
                        Name = Guid.NewGuid().ToString().Substring(1, 5),
                        IP = "127.0.0.1",
                        Comment = "新连接",
                    });
                    _ConnectsModel.SaveConnects();

                    break;

                case "Save":
                    SaveConnects();
                    break;

                case "Remove":
                    if (SelectedClient != null)
                    {
                        Server.Clients.Remove(SelectedClient);
                        SelectedClient = null;
                        _ConnectsModel.SaveConnects();
                    }
                    break;
            }
        }



        private void SaveConnects()
        {
            var names = new List<string>();

            foreach (var item in Server.Clients)
            {
                if (string.IsNullOrEmpty(item.Name))
                {
                    _ConnectsModel.SendErr($"保存失败，名称{item.Name}不合适！", ErrType.ShowDialog);
                    return;
                }

                if (names.Contains(item.Name))
                {
                    _ConnectsModel.SendErr($"保存失败，重复的名称{item.Name}！", ErrType.ShowDialog);
                    return;
                }
                else
                {
                    names.Add(item.Name);
                }
            }


            SelectedClient.Params.Prompt = "";
            _ConnectsModel.SaveConnects();
        }

        #endregion Command
    }
}